package com.coin.authorization.service;

import com.coin.authorization.constant.LoginConstant;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.IncorrectResultSizeDataAccessException;
import org.springframework.jdbc.core.*;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.*;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.*;

import java.sql.*;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Auther: 李 力
 * @Date: 2025/5/23
 * @Description: com.coin.authorization.service
 * @version: 1.0
 */
@Service
public class UserDetailServiceImpl implements UserDetailsService {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        if (StringUtils.isEmpty(username)) {
            throw new AuthenticationServiceException("登录参数为空");
        }
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        String loginType = requestAttributes.getRequest().getParameter("login_type");
        String grantType = requestAttributes.getRequest().getParameter("grant_type");
        if (StringUtils.isEmpty(loginType)) {
            throw new AuthenticationServiceException("login_type登录参数为空");
        }
        if (StringUtils.isEmpty(grantType)) {
            throw new AuthenticationServiceException("grant_type登录参数为空");
        }
        UserDetails userDetails = null;
        try {
            if (LoginConstant.REFRESH_TOKEN.toLowerCase().equals(grantType)) {
                username = adjustUsername(username, loginType);
            }
            switch (loginType) {
                case LoginConstant.ADMIN_TYPE:
                    userDetails = loadAdminUserByUsername(username);
                    break;
                case LoginConstant.MEMBER_TYPE:
                    userDetails = loadMemberUserByUsername(username);
                    break;
                default:
                    throw new AuthenticationServiceException("暂不支持" + loginType + "登录");
            }
            return userDetails;
        } catch (IncorrectResultSizeDataAccessException exception) {
            throw new UsernameNotFoundException("用户不存在");
        }
    }

    //此时参数username是ID
    private String adjustUsername(String username, String loginType) {
        if (LoginConstant.ADMIN_TYPE.equals(loginType)) {
            return jdbcTemplate.queryForObject(LoginConstant.QUERY_ADMIN_USER_WITH_ID, String.class, username);
        }
        if (LoginConstant.MEMBER_TYPE.equals(loginType)) {
            return jdbcTemplate.queryForObject(LoginConstant.QUERY_MEMBER_USER_WITH_ID, String.class, username);
        }
        return username;
    }

    /*
     * 管理员登录
     * */
    private UserDetails loadAdminUserByUsername(String username) {
        //根据用户名查询用户
        User user = jdbcTemplate.queryForObject(LoginConstant.QUERY_ADMIN_SQL, new RowMapper<User>() {
            @Override
            public User mapRow(ResultSet resultSet, int i) throws SQLException {
                if (resultSet.wasNull()) {
                    throw new UsernameNotFoundException("用户不存在");
                }
                long userId = resultSet.getLong("id");
                String password = resultSet.getString("password");
                int status = resultSet.getInt("status");
                return new User(
                        String.valueOf(userId),
                        password,
                        status == 1,
                        true,
                        true,
                        true,
                        getPermissions(userId)
                );
            }
        }, username);
        return user;
    }

    /*
     * 会员登录
     * */
    private UserDetails loadMemberUserByUsername(String username) {
        return jdbcTemplate.queryForObject(LoginConstant.QUERY_MEMBER_SQL, new RowMapper<User>() {
            @Override
            public User mapRow(ResultSet resultSet, int i) throws SQLException {
                if (resultSet.wasNull()) {
                    throw new UsernameNotFoundException("用户不存在");
                }
                long userId = resultSet.getLong("id");
                String password = resultSet.getString("password");
                int status = resultSet.getInt("status");
                return new User(
                        String.valueOf(userId),
                        password,
                        status == 1,
                        true,
                        true,
                        true,
                        Arrays.asList(new SimpleGrantedAuthority("ROLE_USER"))
                );
            }
        }, username, username);
    }

    /*
     * 查询用户权限
     * */
    private Set<SimpleGrantedAuthority> getPermissions(long id) {
        List<String> permissions = null;
        //当用户为管理员拥有所有权限
        String code = jdbcTemplate.queryForObject(LoginConstant.QUERY_ROLE_CODE_SQL, String.class, id);
        if (LoginConstant.ADMIN_ROLE_CODE.equals(code)) {
            permissions = jdbcTemplate.queryForList(LoginConstant.QUERY_ALL_PERMISSIONS, String.class);
        } else {
            //普通用户则不同
            permissions = jdbcTemplate.queryForList(LoginConstant.QUERY_PERMISSION_SQL, String.class, id);
        }
        if (permissions.isEmpty()) {
            return Collections.emptySet();
        }
        Set<SimpleGrantedAuthority> collect = permissions
                .stream()
                .distinct() // 去重
                .map(
                        SimpleGrantedAuthority::new // perm - >security可以识别的权限
                )
                .collect(Collectors.toSet());
        return collect;
    }
}
